<#assign propsJson="${propsJson}"?eval />
<#assign stylesJson="${stylesJson}"?eval />
<template>
  <div style="height: 100%">
    <Table
      ref="tableRef"
      stripe
      :data="extraTableData"
      :columns="columns"
      :max-height="wrapHeight"
      :row-class-name="rowClassName"
    >
    </Table>
  </div>
</template>

<script>
export default {
  name: "autoscroll-table",
  data() {
    return {
      columns: [
        <#assign column=modelJson[0] />
        <#assign ItemKeys=column?keys />
        <#list ItemKeys as ItemKey>
          <#if !ItemKey?starts_with("_")>
            {
              key: "${ItemKey}",
              title: "${ItemKey}",
              minWidth: 100,
              tooltip: true,
            }<#if ItemKey_has_next>,</#if>
          </#if>
        </#list>
      ],
      model: [
        <#list modelJson as Item>
          <#assign ItemKeys=Item?keys />
          {
            <#list ItemKeys as ItemKey>
              <#if !ItemKey?starts_with("_")>
                <#if Item[ItemKey]?is_number || Item[ItemKey]?is_boolean>
                  "${ItemKey}": ${Item[ItemKey]?string}
                <#elseif Item[ItemKey]?is_string>
                  "${ItemKey}": "${Item[ItemKey]?string}"
                </#if>
                <#if ItemKey_has_next>,</#if>
              </#if>
            </#list>
          }<#if Item_has_next>,</#if>
        </#list>
      ],
      tableData: [],
      extraRowData: [],
      currTop: 0,
      rowHeight: 0,
      wrapHeight: ${stylesJson.height},
      theaderHeight: 0,
      wait: 1000,
    };
  },
  computed: {
    extraTableData() {
      return [].concat(this.tableData, this.extraRowData);
    },

    viewHeight() {
      return this.wrapHeight - this.theaderHeight;
    },

    canScroll() {
      return ${propsJson.tbodyOpenScroll?string('true', 'false')} && this.viewHeight < this.tableData.length * this.rowHeight;
    },
  },
  watch: {
    model: {
      handler() {
        this.renderTable();
      },
      immediate: true
    },
  },
  mounted() {
    this.renderTable();
    this.hideTableScrollBar();
    this.$nextTick(() => {
      this.getTableConfig();
    });
  },
  beforeDestroy() {
    this.stop();
    this.removeEvent();
  },
  methods: {
    rowClassName(row) {
      if (row._rowIndex % 2 === 0) {
        return "even-row";
      } else {
        return "odd-row";
      }
    },

    renderTable() {
      // 添加行索引字段，用以设置奇偶行颜色
      this.tableData = this.model.map((v, i) => Object.assign(v, { _rowIndex: i + 1 }));
    },

    hideTableScrollBar() {
      this.$refs.tableRef.scrollBarWidth = 0;
    },

    getTableConfig() {
      this.table = this.$refs.tableRef.$el;
      this.tbody = this.table.querySelector("tbody.ivu-table-tbody");
      const theader = this.table.querySelector(".ivu-table-header");
      this.theaderHeight = theader.offsetHeight;
      this.tbodyHeight = this.tbody.offsetHeight;
      const tr = this.tbody.querySelector("tr.ivu-table-row");
      this.rowHeight = tr.offsetHeight;

      this.tryScroll();
    },

    reset() {
      this.stop();
      this.removeEvent();
      this.extraRowData = [];
      this.currTop = 0;
      if (!this.tbody) return;
      this.tbody.style.transition = "none";
      this.tbody.style.transform = "translate3d(0, 0, 0)";

      this.tryScroll();
    },

    init() {
      // 计算当前高度下最多展示的行数，向上取整
      const showNums = Math.ceil(this.viewHeight / this.rowHeight);
      const sourceNums = this.tableData.length;
      this.maxTop = -this.rowHeight * sourceNums;

      // 追加额外的行数，以达到循环滚动的效果
      this.extraRowData = this.tableData.slice(0, showNums);

      this.scroll();

      // 绑定鼠标移入移出事件
      this.table.addEventListener("mouseenter", this.stop);
      this.table.addEventListener("mouseleave", this.scroll);
    },

    tryScroll() {
      this.canScroll && this.init();
    },

    scroll() {
      this.stop();
      this.timer = setInterval(() => {
        if (this.currTop < this.maxTop) {
          this.currTop = 0;
          this.tbody.style.transition = "none";
        } else {
          // 添加滚动渐进渐出动画
          this.tbody.style.transition = "0.5s transform ease";
        }
        this.tbody.style.transform = "translate3d(0, " + this.currTop + "px, 0)";
        this.currTop -= this.rowHeight;
      }, this.wait);
    },

    stop() {
      clearInterval(this.timer);
      this.timer = null;
    },

    removeEvent() {
      if (!this.table) return;
      this.table.removeEventListener("mouseenter", this.stop);
      this.table.removeEventListener("mouseleave", this.scroll);
    },
  },
}
</script>
<style lang="less" scoped>
::v-deep .ivu-table-overflowY {
  overflow-y: hidden;
}

/deep/ .ivu-table-border {
  height: 0px !important;
}
/deep/ .ivu-table {
  background: transparent;
  border-color: #1890ff;

  th {
    background: transparent;
    border: none;
  }

  td {
    background: transparent;
    border: none;
  }

  &::before {
    height: 0px !important;
  }
}

/deep/ .ivu-table-stripe .ivu-table-body tr:nth-child(2n) td,
.ivu-table-stripe .ivu-table-fixed-body tr:nth-child(2n) td {
  background: rgba(255, 255, 255, 0);
}

/deep/ .ivu-table-stripe .ivu-table-body tr.ivu-table-row-hover td,
.ivu-table-stripe .ivu-table-fixed-body tr.ivu-table-row-hover td {
  background: rgba(255, 255, 255, 0.1);
}

/deep/ .ivu-table-header tr {
  color: "${propsJson.theaderFontColor}";
  font-size: ${propsJson.theaderFontSize}px;
  font-style: ${propsJson.theaderFontStyles?seq_contains("italic")?string("italic", "normal")};
  background: "${propsJson.theaderBackColor}";

  th {
    text-align: ${propsJson.theaderAlign};
    font-weight: ${propsJson.theaderFontStyles?seq_contains("bold")?string("bold", "normal")} !important;

    .ivu-table-cell {
      text-decoration: ${propsJson.theaderFontStyles?seq_contains("underline")?string("underline", "none")};
    }
  }
}

/deep/ .ivu-table-tbody tr {
  color: ${propsJson.tbodyFontColor};
  font-size: ${propsJson.tbodyFontSize}px;
  font-style: ${propsJson.tbodyFontStyles?seq_contains("italic")?string("italic", "normal")};

  td {
    text-align: ${propsJson.tbodyAlign};
    font-weight: ${propsJson.tbodyFontStyles?seq_contains("bold")?string("bold", "normal")} !important;

    .ivu-table-cell {
      text-decoration: ${propsJson.tbodyFontStyles?seq_contains("underline")?string("underline", "none")};
    }
  }

  &.even-row {
    background: ${propsJson.tbodyEvenRowColor};
  }

  &.odd-row {
    background: ${propsJson.tbodyOddRowColor};
  }
}
</style>

